/*
    KMC Simulation
    Copyright (c) 2012-2014 Filip Rozbořil

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "ProxyEvent.h"
#include "Random.h"

class PartialEvent : public ProxyEvent
{
	private:
		vector<ProxyEvent*> mSubEvents;
		 
	protected:
		virtual void execute(Random* r);

	public:
		PartialEvent(uint32_t capacity) : ProxyEvent() { mSubEvents.reserve(capacity); }
		virtual ~PartialEvent() { for(auto e : mSubEvents) delete e; }
		void addSubEvent(ProxyEvent* ev) { mSubEvents.push_back(ev); }
		virtual string getName() { return "Partial event"; }
		virtual bool updateRate();
		virtual void printCount(ostream& os);
};

inline void PartialEvent :: execute(Random* r)
{
	double pivot = r->getDouble() * getRate();
	auto i = mSubEvents.begin();
 	double probe = (*i)->getRate();
 	
	while(probe < pivot)
	{
		++i;
		probe += (*i)->getRate();
	}
	
	(*i)->handle(r);
}

inline bool PartialEvent :: updateRate()
{
	bool updated = false;
	for(auto e : mSubEvents)
	{
		if(e->updateRate())
		{
			updated = true;
		}
	}
	if(updated) //only recalculate the rate of the super-event if the rate some sub-event changed
	{			//this saves us some floating point math, leading to a small speed up
		double rate = 0.0;
		for(auto e : mSubEvents)
		{
			rate += e->getRate();
		}
		setRate(rate);
	}
	return updated;
}

inline void PartialEvent :: printCount(ostream& os)
{
	for(auto e : mSubEvents)
	{
		e->printCount(os);
	}
}
